<template>
  <a-modal
    :visible="visible"
    :title="title"
    :width="600"
    :bodyStyle="{ padding: '24px 0' }"
    :maskClosable="false"
    @ok="handleModalOk"
    @cancel="handleModalCancel"
    :confirmLoading="confirmLoading"
  >
    <a-spin :spinning="loading || confirmLoading">
      <a-row>
        <a-col :span="13">
          <div class="picker-left">
            <search
              ref="search"
              pinyin="fullPinyin"
              py="simplicity"
              :party="partyList"
              :member="memberList"
              :mode="mode"
              :selectedKeys="selectedKeys"
              @onSelect="selectSearchResult"
              @change="onSearch"
            />
            <a-tree
              v-show="!searching"
              class="picker-left-tree"
              multiple
              blockNode
              showIcon
              :treeData="treeData"
              :replaceFields="replaceFields"
              :expandedKeys.sync="expandedKeys"
              :selectedKeys="selectedKeys"
              @select="onSelect"
            >
              <a-icon slot="icon" type="folder" />
              <a-icon slot="extraIcon" type="user" />
            </a-tree>
          </div>
        </a-col>
        <a-col :span="11">
          <div class="picker-right">
            <template v-if="mode.includes('member')">
              <div class="picker-right-title">已选择的成员</div>
              <div class="picker-selected-list">
                <div class="picker-selected-item" v-for="node in selectedNodes.memberList" :key="node.key">
                  <a-icon type="user" />
                  <span class="picker-selected-item-name">{{ node[UserPickerOptions.memberProp] }}</span>
                  <a href="javascript:;" @click="removeNode(node.key)">
                    <a-icon type="close" />
                  </a>
                </div>
              </div>
            </template>
            <template v-if="mode.includes('party')">
              <div class="picker-right-title">已选择的部门</div>
              <div class="picker-selected-list">
                <div class="picker-selected-item" v-for="node in selectedNodes.partyList" :key="node.key">
                  <a-icon type="folder" />
                  <span class="picker-selected-item-name">{{ node[UserPickerOptions.partyProp] }}</span>
                  <a href="javascript:;" @click="removeNode(node.key)">
                    <a-icon type="close" />
                  </a>
                </div>
              </div>
            </template>
          </div>
        </a-col>
      </a-row>
    </a-spin>
  </a-modal>
</template>

<script>
import Search from './Search'
import { readAllOrg, readAllUser } from '@/api/organization'
import { setArrayToTree, breadFirstTree } from '@/utils/util'
import { UserPickerOptions } from './options'
import intersection from 'lodash/intersection'

export default {
  name: 'UserPicker',
  components: {
    Search
  },
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: '添加人员'
    },
    mode: {
      type: Array,
      default: ['member', 'party']
    },
    defaultSelectedKeys: {
      type: Array,
      required: false,
      default: () => []
    },
    disabledMemberProp: {
      type: String
    }
  },
  data () {
    return {
      partyList: [],
      memberList: [],
      replaceFields: {
        children: UserPickerOptions.collection,
        title: 'name'
      },
      searching: false,
      selectedKeys: [],
      expandedKeys: [],
      UserPickerOptions,
      confirmLoading: false,
      loading: false
    }
  },
  computed: {
    treeData () {
      // 根据 mode 设置节点是否可选中
      const partyList = this.partyList
      const memberList = this.memberList
      // 人员和部门 id 可能相同，这里自定义key
      partyList.forEach(item => (item.key = 'party' + item.id))
      memberList.forEach(item => (item.key = 'member' + item.id))

      // 禁用已是平台管理员的人员
      if (this.disabledMemberProp) {
        memberList.forEach(user => (user.selectable = !user[this.disabledMemberProp]))
        memberList.forEach(user => (user.disabled = user[this.disabledMemberProp]))
      }

      if (!this.mode.includes('party')) {
        partyList.forEach(item => (item.selectable = false))
      }

      if (!this.mode.includes('member')) {
        memberList.forEach(item => (item.selectable = false))
      }

      // 组织及人员树状结构
      const tree = setArrayToTree({
        ...UserPickerOptions,
        data: partyList,
        extraData: memberList,
        extraIcon: 'extraIcon'
      })
      if (this.mode.includes('party')) {
        breadFirstTree(
          tree,
          node => {
            node.child &&
              node.child.forEach(c => {
                c.parentIds = c.parentIds || `${node.parentIds || ''}[${node.id}]`
              })
            const selectPartyIds = this.selectedKeys
              .filter(k => /party/.test(k))
              .map(item => +item.replace('party', ''))
            const regExp = new RegExp(`(?<=\\[).*?(?=\\])`, 'g')
            const parentIdsList = node.parentIds ? node.parentIds.match(regExp).map(i => Number(i)) : []
            node.disabled = !!intersection(selectPartyIds, parentIdsList).length
            if (intersection(selectPartyIds, parentIdsList).length) {
              this.removeNode(node.key)
            }
            return true
          },
          'child'
        )
      }
      return tree
    },
    // 根据选中的 key 转换实体
    selectedNodes () {
      const nodes = {
        memberList: [],
        partyList: []
      }
      this.selectedKeys.forEach(key => {
        if (key.indexOf('member') > -1) {
          const item = this.memberList.find(item => item.key === key)
          if (item) {
            nodes.memberList.push(item)
          }
        } else {
          const item = this.partyList.find(item => item.key === key)
          if (item) {
            nodes.partyList.push(item)
          }
        }
      })

      return nodes
    }
  },
  watch: {
    visible (val) {
      if (this.partyList.length === 0) {
        this.loading = true
        Promise.all([this.getAllOrg(), this.getAllUser()]).then(() => {
          this.loading = false
        })
      }

      // 默认选择的节点
      if (val && this.defaultSelectedKeys.length > 0) {
        this.selectedKeys = [...this.defaultSelectedKeys]
      }

      // 窗口关闭
      if (!val) {
        // 清除搜索区域
        if (this.searching) {
          this.$refs.search.clearSearch()
        }
        this.selectedKeys = []
        this.expandedKeys = []
      }
    },
    mode (val) {
      // 不同模式下，节点禁用问题
      this.partyList.forEach(item => (item.selectable = true))
      this.memberList.forEach(item => (item.selectable = true))
    }
  },
  methods: {
    handleModalOk () {
      this.confirmLoading = true
      this.$emit('ok', this.selectedNodes)
    },
    handleModalCancel () {
      this.resetModal()
    },
    resetModal () {
      this.$emit('close')
      this.selectedKeys = []
      this.confirmLoading = false
    },
    // 获取所有部门
    async getAllOrg () {
      const res = await readAllOrg()
      if (res.code === 'sso.ok') {
        this.partyList = res.data || []
      }
    },
    // 获取所有人员
    async getAllUser () {
      const res = await readAllUser()
      if (res.code === 'sso.ok') {
        this.memberList = res.data || []
      }
    },
    // 搜索框状态
    onSearch (searching) {
      this.searching = searching
    },
    // 选择搜索项
    selectSearchResult (key) {
      this.selectedKeys.push(key)
    },
    onSelect (selectedKeys, e) {
      this.selectedKeys = selectedKeys
    },
    // 移除已选中节点
    removeNode (id) {
      this.selectedKeys = this.selectedKeys.filter(key => key !== id)
    }
  }
}
</script>

<style lang="less" scoped>
@height-base: 410px;

.picker-left {
  display: flex;
  flex-direction: column;
  height: @height-base;
  padding-left: 24px;
  border-right: 1px solid #e8e8e8;
  overflow: auto;

  &-tree {
    flex: 1;
    padding-right: 20px;
    overflow: auto;
  }
}
.picker-right {
  display: flex;
  flex-direction: column;
  padding-left: 20px;
  height: @height-base;

  &-title {
    margin-bottom: 10px;
    font-size: 14px;
    color: #787878;

    &:not(:first-of-type) {
      margin-top: 4px;
    }
  }

  .picker-selected-list {
    flex: 1;
    padding-right: 20px;
    overflow-y: auto;

    .picker-selected-item {
      display: flex;
      align-items: center;
      height: 30px;
      line-height: 30px;

      &-name {
        flex: 1;
        margin: 0 7px;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
      }

      a {
        color: inherit;

        &:hover {
          color: #1890ff;
        }
      }
    }
  }
}
</style>
